本地生成自签名证书
在开发环境中测试 HTTPS,需要先生成自签名证书:
# 生成私钥和证书(有效期 365 天)
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
# 或者更简洁的方式
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes -subj "/CN=localhost"
bash
-x509:生成自签名证书-newkey rsa:2048:生成 2048 位 RSA 密钥-keyout:私钥输出路径-out:证书输出路径-days 365:有效期 365 天-nodes:不加密私钥(开发环境使用)-subj "/CN=localhost":设置 Common Name 为 localhost
在 NestJS 中启用 HTTPS
// main.ts
import { NestFactory } from '@nestjs/core'
import { AppModule } from './app.module'
import { WsAdapter } from '@nestjs/platform-ws'
import * as fs from 'fs'
import * as path from 'path'
async function bootstrap() {
const httpsOptions = {
key: fs.readFileSync(path.resolve('certs/key.pem')),
cert: fs.readFileSync(path.resolve('certs/cert.pem')),
}
const app = await NestFactory.create(AppModule, {
httpsOptions,
})
app.useWebSocketAdapter(new WsAdapter(app))
await app.listen(3000)
console.log('HTTPS Server running on https://localhost:3000')
}
bootstrap()
typescript
关键点:NestFactory.create 的第二个参数传入 httpsOptions 对象,包含 key 和 cert。
本地测试 HTTPS
浏览器访问 https://localhost:3000 时会显示安全警告(因为证书是自签名的,不被浏览器信任)。点击"高级" -> "继续前往"即可。
解决 Chrome 的安全警告
在 Chrome 地址栏输入以下内容可以跳过 localhost 的证书检查:
chrome://flags/#allow-insecure-localhost
text
将 "Allow invalid certificates for resources loaded from localhost" 设置为 Enabled。
WebSocket 安全连接(WSS)
启用 HTTPS 后,WebSocket 连接也需要升级为安全版本。将客户端的连接地址从 ws:// 改为 wss://:
// 之前
const ws = new WebSocket('ws://localhost:3000')
// 启用 HTTPS 后
const ws = new WebSocket('wss://localhost:3000')
javascript
WSS(WebSocket Secure)与 HTTPS 共享同一个 TLS 连接,使用相同的证书。在 Nginx 反向代理场景下,Nginx 负责终止 TLS,后端的 NestJS 可以继续使用 HTTP。
证书文件管理
将证书文件放在项目的 certs/ 目录下,并在 .gitignore 中排除:
# .gitignore
certs/
*.pem
gitignore
自签名证书仅用于开发环境,生产环境必须使用 CA 签发的正式证书(如 Let's Encrypt)。
↑